package com.tianma315.admin.statisticstable.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.tianma315.admin.check.domain.CheckArrtDO;
import com.tianma315.admin.check.domain.RecordArrtDO;
import com.tianma315.admin.check.service.CheckArrtService;
import com.tianma315.admin.check.vo.RecordArrtVO;
import com.tianma315.admin.common.exception.HtmlCodeException;
import com.tianma315.admin.common.exception.IFastException;
import com.tianma315.admin.common.exception.MessageException;
import com.tianma315.admin.common.service.ConfigService;
import com.tianma315.admin.common.type.EnumErrorCode;
import com.tianma315.admin.common.utils.DateUtils;
import com.tianma315.admin.common.utils.DoubleUtils;
import com.tianma315.admin.material.VO.PurchaseAndArrtVO;
import com.tianma315.admin.material.service.PurchaseService;
import com.tianma315.admin.product.domain.Product;
import com.tianma315.admin.product.service.ProductService;
import com.tianma315.admin.statisticstable.service.StatisticsService;
import com.tianma315.admin.stock.domain.vo.WarehousingRecordAndArrtVO;
import com.tianma315.admin.stock.service.StockService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

@Service
public class StatisticsServiceImpl implements StatisticsService {
    @Autowired
    private PurchaseService purchaseService;

    @Autowired
    private StockService stockService;

    @Autowired
    private CheckArrtService checkArrtService;

    @Autowired
    private ProductService productService;

    @Autowired
    private ConfigService configService;

    @Override
    public Page statisticsProductTable(Integer pageNumber, Integer pageSize,List<Integer> productIds, Date beginDate,Date endDate) {
        Page page = new Page<>(pageNumber, pageSize);
        List<WarehousingRecordAndArrtVO> wrList =  stockService.statisticsTable(page,productIds,beginDate,endDate);
//        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();

        List<String> boxHeadList = new ArrayList<>();
        List contentList = null;

        if (wrList==null || wrList.isEmpty()){
          throw  new HtmlCodeException("未找到检测记录");
        }else {

            for (int i = 0; i < wrList.size(); i++) {
                WarehousingRecordAndArrtVO wr = wrList.get(i);

                //表头
                List<CheckArrtDO> checkArrtDOList = wr.getCheckArrtDOList();

                //上一条数据和现这条数据不一
                if ((boxHeadList.size()-6) != checkArrtDOList.size()){
                    boxHeadList = new ArrayList<>();
                    boxHeadList.add("序号");
                    boxHeadList.add("检测时间");
                    boxHeadList.add("产品名称");
                    boxHeadList.add("编号");
                    boxHeadList.add("检测人");
                    boxHeadList.add("入库时间");
                    //每个产品只能对应一套模板，此时虽然多条数据，但取其一就可以

                    for (CheckArrtDO checkArrtDO:checkArrtDOList) {
                        boxHeadList.add(checkArrtDO.getArrtName());
                    }
                    jsonArray.add(boxHeadList);
                }


                Integer orderNumber = i + 1;
                contentList = new ArrayList<>();
                contentList.add(orderNumber.toString());
                contentList.add(DateUtils.format(wr.getCreateDate()));
                contentList.add(wr.getProductName());
                contentList.add(wr.getBatch());
                contentList.add(wr.getCheckBy());
                contentList.add(DateUtils.format(wr.getProduceDate()));

                //遍历属性值
                List<RecordArrtVO> recordArrtDOS = wr.getRecordArrtVOS();
                List<CheckArrtDO> checkArrtDOS = wr.getCheckArrtDOList();
                for (int j = 0; j < recordArrtDOS.size(); j++) {
                    RecordArrtDO recordArrtDO = recordArrtDOS.get(j);
                    CheckArrtDO checkArrtDO = checkArrtDOS.get(j);
                    Map map = new HashMap();
                    map.put("attrValue",recordArrtDO.getArrtValues());
                    map.put("min",checkArrtDO.getMinimum());
                    map.put("max",checkArrtDO.getMaximum());
                    contentList.add(map);
                }

                jsonArray.add(contentList);
            }
        }
        page.setRecords(jsonArray);
        return page;
    }

    @Override
    public JSONObject statisticsProductAllTable(Date beginDate, Date endDate) {
        List<WarehousingRecordAndArrtVO> list  =  stockService.statisticsAllTable(beginDate,endDate);
        JSONObject obj = new JSONObject();

        if (list==null || list.isEmpty()){
            throw new HtmlCodeException("未找到检测记录");
        }else {
            //一级表头
            List headList = new ArrayList();
            headList.add("NO");
            headList.add("产品名称");
            headList.add("合格");

            //获取动态一级表头,以及获取所有的检测模板属性
            List heads = new ArrayList();
//            List<CheckArrtDO> checkArrtDOList = new ArrayList<>();
            for (WarehousingRecordAndArrtVO warehousingRecordAndArrtVO:list) {
                for (CheckArrtDO checkArrtDO:warehousingRecordAndArrtVO.getCheckArrtDOList()) {
                    if (!heads.contains(checkArrtDO.getArrtName())){
                        heads.add(checkArrtDO.getArrtName());
//                        checkArrtDOList.add(checkArrtDO);
                    }
//                    if (!checkArrtDOList.contains(checkArrtDO)){
//                        checkArrtDOList.add(checkArrtDO);
//                    }
                }
            }
            headList.addAll(heads);

            List resultList = new ArrayList();
            for (int i = 0; i < list.size(); i++) {
                List result = new ArrayList();
                List<CheckArrtDO> checkArrtDOList = new ArrayList<>();//属性范围列表

                WarehousingRecordAndArrtVO warehousingRecordAndArrtVO = list.get(i);
                for (CheckArrtDO checkArrtDO:warehousingRecordAndArrtVO.getCheckArrtDOList()) {
                    checkArrtDOList.add(checkArrtDO);//将属性范围值添加集合中去
                }

                Integer orderNo = i+1;//编号
                result.add(orderNo);
                String name = warehousingRecordAndArrtVO.getProductName();//原料名称
                result.add(name);
                Integer countNum = warehousingRecordAndArrtVO.getCountNum();//次数

                //每个原材料检测次数纪录
                Map<String,List<Double>> map = new HashMap();
                for (RecordArrtVO recordArrtDO:warehousingRecordAndArrtVO.getRecordArrtVOS()) {
                    Double arrt = 0.0;
                    if (StringUtils.isNotEmpty(recordArrtDO.getArrtValues())){
                        arrt = Double.valueOf(recordArrtDO.getArrtValues());
                    }

                    List<Double> numListByMap = map.get(recordArrtDO.getArrtName());
                    List<Double>  numList = new ArrayList<>();
                    if (numListByMap == null || numListByMap.size() == 0){
                        numList.add(arrt);
                        map.put(recordArrtDO.getArrtName(),numList);
                    }else{
                        numListByMap.add(arrt);
                        map.put(recordArrtDO.getArrtName(),numListByMap);
                    }
                }

                //便利原材料检测次数纪录求平均值，合格率，偏高，偏低

                Double passRate = 100.0;
//            for (Integer key:map.keySet()){
                for (int j = 0; j < checkArrtDOList.size(); j++) {
                    Map recordMap = new HashMap();
                    CheckArrtDO c = checkArrtDOList.get(j);
                    if (map.keySet().contains(c.getArrtName())){
                        Double sum = 0.0;
                        List<Double> num =map.get(c.getArrtName());
                        Integer highCount = 0;//偏高次数
                        Integer flatCount = 0;//偏低次数
                        Integer rightCount = 0;//合格次数
                        for (Double n:num) {
                            sum= sum + n;
                        }
                        Double avgNum = sum/countNum;//取平均值
                        BigDecimal b = new BigDecimal(avgNum);
                        avgNum = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//四舍五入保留两位小数
                        recordMap.put("countNum",countNum);//次数
                        recordMap.put("avgNum",avgNum);//平均值

                        for (Double n:num) {
                            if (n>c.getMaximum()){
                                highCount++;
                            }else if (n<c.getMinimum()){
                                flatCount++;
                            }else{
                                rightCount++;
                            }
                        }
                        recordMap.put("consultNum",c.getMinimum()+"-"+c.getMaximum());//参考值
                        Double high = DoubleUtils.division(highCount,num.size());//偏高值
                        Double flat = DoubleUtils.division(flatCount,num.size());//偏低值
                        Double right = DoubleUtils.division(rightCount,num.size());//合格率
                        //取出总合格率，passRate为空时，说明第一次赋值给passRate，不为空时，判断passRate是否大于right，是则替换
//                        if (passRate == null ||passRate.equals(0.0)){
//                            passRate = right;
//                        }else{
                        if (right < passRate){
                            passRate = right;
                        }
//                        }
                        recordMap.put("high",high+"%");
                        recordMap.put("flat",flat+"%");
                        recordMap.put("right",right+"%");

                    }else{
                        recordMap.put("high","-");
                        recordMap.put("flat","-");
                        recordMap.put("right","-");
                        recordMap.put("countNum","-");//次数
                        recordMap.put("avgNum","-");//平均值
                        recordMap.put("consultNum",c.getMinimum()+"-"+c.getMaximum());//参考值
                    }
                    result.add(recordMap);
                }

                //总合格率，取最低那个合格率
//            for (int j = 2; j < result.size(); j++) {
//                Map resultMap = (Map) result.get(j);
//
//
//            }
//            }
                result.add(2,passRate+"%");//插入到下标2位置
                resultList.add(result);
            }






            //二级表头
            List subTitle = new ArrayList();
            subTitle.add("次数");
            subTitle.add("平均值");
            subTitle.add("参考值");
            subTitle.add("偏高");
            subTitle.add("偏低");
            subTitle.add("合格");

            obj.put("head",headList);
            obj.put("subTitle",subTitle);
            obj.put("content",resultList);
        }

        return obj;
    }

    public JSONObject statisticsMaterialAllTable(List<Integer> materialIds, Date beginDate,Date endDate){
    JSONObject obj = new JSONObject();

    List<PurchaseAndArrtVO> list = purchaseService.statisticsMaterialAllTable(null,beginDate,endDate);
    if (list==null || list.isEmpty()){
//        throw new IFastException(EnumErrorCode.nullList2.getCodeStr());
        throw new HtmlCodeException("未找到检测记录");
    }else {
        //一级表头
        List headList = new ArrayList();
        headList.add("NO");
        headList.add("产品名称");
        headList.add("合格");

        //获取动态一级表头,以及获取所有的检测模板属性
        List heads = new ArrayList();
        List<CheckArrtDO> checkArrtDOList = new ArrayList<>();
        for (PurchaseAndArrtVO purchaseAndArrtVO:list) {
            for (CheckArrtDO checkArrtDO:purchaseAndArrtVO.getCheckArrtDOList()) {
                if (!heads.contains(checkArrtDO.getArrtName())){
                    heads.add(checkArrtDO.getArrtName());
                    checkArrtDOList.add(checkArrtDO);
                 }
            }
        }
        headList.addAll(heads);

        List resultList = new ArrayList();
        for (int i = 0; i < list.size(); i++) {
            List result = new ArrayList();
            PurchaseAndArrtVO purchaseAndArrtVO = list.get(i);
            Integer orderNo = i+1;//编号
            result.add(orderNo);
            String name = purchaseAndArrtVO.getMaterialName();//原料名称
            result.add(name);
            Integer countNum = purchaseAndArrtVO.getCountNum();//次数

            //每个原材料检测次数纪录
            Map<Integer,List<Double>> map = new HashMap();
            for (RecordArrtVO recordArrtDO:purchaseAndArrtVO.getRecordArrtVOS()) {
                Double arrt = 0.0;
                if (StringUtils.isNotEmpty(recordArrtDO.getArrtValues())){
                    arrt = Double.valueOf(recordArrtDO.getArrtValues());
                }

                List<Double> numListByMap = map.get(recordArrtDO.getCheckArrtId());
                List<Double>  numList = new ArrayList<>();
                if (numListByMap == null || numListByMap.size() == 0){
                    numList.add(arrt);
                    map.put(recordArrtDO.getCheckArrtId(),numList);
                }else{
                    numListByMap.add(arrt);
                    map.put(recordArrtDO.getCheckArrtId(),numListByMap);
                }
            }

            //便利原材料检测次数纪录求平均值，合格率，偏高，偏低

            Double passRate = 100.0;
//            for (Integer key:map.keySet()){
                for (int j = 0; j < checkArrtDOList.size(); j++) {
                    Map recordMap = new HashMap();
                    CheckArrtDO c = checkArrtDOList.get(j);
                    if (map.keySet().contains(c.getCheckArrtId())){
                        Double sum = 0.0;
                        List<Double> num =map.get(c.getCheckArrtId());
                        Integer highCount = 0;//偏高次数
                        Integer flatCount = 0;//偏低次数
                        Integer rightCount = 0;//合格次数
                        for (Double n:num) {
                            sum= sum + n;
                        }
                        Double avgNum = sum/countNum;//取平均值
                        BigDecimal b = new BigDecimal(avgNum);
                        avgNum = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();//四舍五入保留两位小数
                        recordMap.put("countNum",countNum);//次数
                        recordMap.put("avgNum",avgNum);//平均值

                        for (Double n:num) {
                            if (n>c.getMaximum()){
                                highCount++;
                            }else if (n<c.getMinimum()){
                                flatCount++;
                            }else{
                                rightCount++;
                            }
                        }
                        recordMap.put("consultNum",c.getMinimum()+"-"+c.getMaximum());//参考值
                        Double high = DoubleUtils.division(highCount,num.size());//偏高值
                        Double flat = DoubleUtils.division(flatCount,num.size());//偏低值
                        Double right = DoubleUtils.division(rightCount,num.size());//合格率
                        //取出总合格率，passRate为空时，说明第一次赋值给passRate，不为空时，判断passRate是否大于right，是则替换
//                        if (passRate == null ||passRate.equals(0.0)){
//                            passRate = right;
//                        }else{
                            if (right < passRate){
                                passRate = right;
                            }
//                        }
                        recordMap.put("high",high+"%");
                        recordMap.put("flat",flat+"%");
                        recordMap.put("right",right+"%");

                    }else{
                        recordMap.put("high","-");
                        recordMap.put("flat","-");
                        recordMap.put("right","-");
                        recordMap.put("countNum","-");//次数
                        recordMap.put("avgNum","-");//平均值
                        recordMap.put("consultNum",c.getMinimum()+"-"+c.getMaximum());//参考值
                    }
                    result.add(recordMap);
                }

            //总合格率，取最低那个合格率
//            for (int j = 2; j < result.size(); j++) {
//                Map resultMap = (Map) result.get(j);
//
//
//            }
//            }
            result.add(2,passRate+"%");//插入到下标2位置
            resultList.add(result);
        }



        //二级表头
        List subTitle = new ArrayList();
        subTitle.add("次数");
        subTitle.add("平均值");
        subTitle.add("参考值");
        subTitle.add("偏高");
        subTitle.add("偏低");
        subTitle.add("合格");

        obj.put("head",headList);
        obj.put("subTitle",subTitle);
        obj.put("content",resultList);
    }

    return obj;
    }

    public Page statisticsMaterialTable(Integer pageNumber, Integer pageSize,List<Integer> materialIds,Date beginDate,Date endDate){
        Page page = new Page<>(pageNumber, pageSize);
        List<PurchaseAndArrtVO> wrList =  purchaseService.statisticsMaterialTable(page,materialIds,beginDate,endDate);
//        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();

        List<String> boxHeadList = new ArrayList<>();
        List contentList = null;

        if (wrList==null || wrList.isEmpty()){
            throw  new HtmlCodeException("未找到检测记录");
        }else {
            //每个产品只能对应一套模板，此时虽然多条数据，但取其一就可以
            //表头
//            jsonObject.put("head",boxHeadList);


            for (int i = 0; i < wrList.size(); i++) {
                //标题头


                //表格数据
                PurchaseAndArrtVO wr = wrList.get(i);

                List<CheckArrtDO> checkArrtDOList = wr.getCheckArrtDOList();
                //上一条数据和现这条数据不一
                if ((boxHeadList.size()-6) != checkArrtDOList.size()) {
                    boxHeadList = new ArrayList<>();
                    boxHeadList.add("序号");
                    boxHeadList.add("检测时间");
                    boxHeadList.add("产品名称");
                    boxHeadList.add("批次号");
                    boxHeadList.add("检测人");
                    boxHeadList.add("入库时间");

                    for (CheckArrtDO checkArrtDO : checkArrtDOList) {
                        boxHeadList.add(checkArrtDO.getArrtName());
                    }
                    jsonArray.add(boxHeadList);
                }

                Integer orderNumber = i + 1;
                contentList = new ArrayList<>();
                contentList.add(orderNumber.toString());
                contentList.add(DateUtils.format(wr.getInStockDate()));
                contentList.add(wr.getMaterialName());
                contentList.add(wr.getPurchaseNo());
                contentList.add(wr.getPurchaser());
                contentList.add(DateUtils.format(wr.getInStockDate()));

                //遍历属性值
                List<RecordArrtVO> recordArrtDOS = wr.getRecordArrtVOS();
                List<CheckArrtDO> checkArrtDOS = wr.getCheckArrtDOList();
                for (int j = 0; j < recordArrtDOS.size(); j++) {
                    RecordArrtDO recordArrtDO = recordArrtDOS.get(j);
                    CheckArrtDO checkArrtDO = checkArrtDOS.get(j);
                    Map map = new HashMap();
                    map.put("attrValue",recordArrtDO.getArrtValues());
                    map.put("min",checkArrtDO.getMinimum());
                    map.put("max",checkArrtDO.getMaximum());
                    contentList.add(map);
                }


                jsonArray.add(contentList);
            }
        }
//        jsonObject.put("content",jsonArray);
        page.setRecords(jsonArray);
        return page;

    }

}
